/************************************************************************

								Heroes IV
					  Copyright 2000, The 3DO Company

	------------------------------------------------------------------
  						       building_traits.cpp

	$Header: /game/building_traits.cpp $

	$NoKeywords: $

 ************************************************************************/

// kill the 255+ character identifier warning.  Templates tend to exceed that easily.
#include "precompiled.h"
#pragma warning( disable: 4786 )

#include "building_traits.h"

#include "adv_object_type.h"
#include "creature_traits.h"
#include "creature_type.h"
#include "elements_of.h"
#include "table.h"
#include "table_ptr.h"
#include "town_building.h"
#include "town_image_level.h"
#include "town_type.h"

namespace
{
	t_building_traits k_building_traits[k_town_type_count][k_town_building_count];
	t_table_cache     g_building_table( "buildings" );

	// --------------------------------------------------------
	// names of layers in layouts 
	// --------------------------------------------------------

	// common buildings, for life to might
	struct t_layout_layer_name
	{
		t_town_building id;
		char const*     name;
	};
		
	t_layout_layer_name const k_common_layers[] =
	{
		{ k_town_village_hall,	"village hall" },
		{ k_town_hall,			"town hall" },
		{ k_town_city_hall,		"city hall" },
		{ k_town_fort,			"fort" },
		{ k_town_citadel,		"citadel" },
		{ k_town_castle,		"castle" },
		{ k_town_shipyard,		"shipyard" },
		{ k_town_caravan,		"caravan" },
		{ k_town_prison,		"prison" },
		{ k_town_tavern,		"tavern" },
		{ k_town_blacksmith,	"blacksmith" },
		{ k_town_grail,			"grail" },
	};

	t_layout_layer_name const k_life_layers[] =
	{
		{ k_town_mage_guild_1,  "mage guild 1" },
		{ k_town_mage_guild_2,	"mage guild 2" },
		{ k_town_mage_guild_3,	"mage guild 3" },
		{ k_town_mage_guild_4,	"mage guild 4" },
		{ k_town_mage_guild_5,	"mage guild 5" },
		{ k_town_library_1,				"nature library" },
		{ k_town_library_2,				"order library" },
		{ k_town_seminary,				"seminary" },
		{ k_town_stables,				"stables" },
		{ k_town_abbey,					"abbey" },
		{ k_town_dwelling_squire,		"squire guild" },
		{ k_town_dwelling_crossbowman,	"archery range" },
		{ k_town_dwelling_pikeman,		"guardhouse" },
		{ k_town_dwelling_ballista,		"ballista works" },
		{ k_town_dwelling_crusader,		"barracks" },
		{ k_town_dwelling_monk,			"monastary" },
		{ k_town_dwelling_champion,		"knight chapter" },
		{ k_town_dwelling_angel,		"altar of light" }
	};

	t_layout_layer_name const k_order_layers[] = 
	{
		{ k_town_mage_guild_1,  "mage guild 1" },
		{ k_town_mage_guild_2,	"mage guild 2" },
		{ k_town_mage_guild_3,	"mage guild 3" },
		{ k_town_mage_guild_4,	"mage guild 4" },
		{ k_town_mage_guild_5,	"mage guild 5" },
		{ k_town_library_1,				"life library" },
		{ k_town_library_2,				"death library" },
		{ k_town_university,			"university" },
		{ k_town_treasury,				"treasury" },
		{ k_town_dwelling_dwarf,		"dwarven mines" },
		{ k_town_dwelling_halfling,		"halfling burrow" },
		{ k_town_dwelling_golem,		"golem factory" },
		{ k_town_dwelling_mage,			"mage tower" },
		{ k_town_dwelling_naga,			"golden pavilion" },
		{ k_town_dwelling_genie,		"altar of wishes" },
		{ k_town_dwelling_dragon_golem, "dragon factory" },
		{ k_town_dwelling_titan,		"cloud castle" },
	};

	t_layout_layer_name const k_death_layers[] =
	{
		{ k_town_mage_guild_1,  "mage guild 1" },
		{ k_town_mage_guild_2,	"mage guild 2" },
		{ k_town_mage_guild_3,	"mage guild 3" },
		{ k_town_mage_guild_4,	"mage guild 4" },
		{ k_town_mage_guild_5,	"mage guild 5" },
		{ k_town_library_1,				"order library" },
		{ k_town_library_2,				"chaos library" },
		{ k_town_skeleton_transformer,	"skeleton transformer" },
		{ k_town_necromancy_amplifier,	"necromancy amplifier" },
		{ k_town_dwelling_skeleton,		"cemetery" },
		{ k_town_dwelling_imp,			"torture chamber" },
		{ k_town_dwelling_ghost,		"barrow mound" },
		{ k_town_dwelling_cerberus,		"kennels" },
		{ k_town_dwelling_vampire,		"mansion" },
		{ k_town_dwelling_venom_spawn,	"spawn pit" },
		{ k_town_dwelling_bone_dragon,	"dragon graveyard" },
		{ k_town_dwelling_devil,		"temple of the damned" }
	};

	t_layout_layer_name const k_chaos_layers[] =
	{
		{ k_town_mage_guild_1,  "mage guild 1" },
		{ k_town_mage_guild_2,	"mage guild 2" },
		{ k_town_mage_guild_3,	"mage guild 3" },
		{ k_town_mage_guild_4,	"mage guild 4" },
		{ k_town_mage_guild_5,	"mage guild 5" },
		{ k_town_library_1,				"death library" },
		{ k_town_library_2,				"nature library" },
		{ k_town_academy,				"academy" },
		{ k_town_training_grounds,		"training grounds" },
		{ k_town_mana_vortex,			"mana vortex" },
		{ k_town_dwelling_bandit,		"bandit gen" },
		{ k_town_dwelling_orc,			"orc camp" },
		{ k_town_dwelling_medusa,		"statuary garden" },
		{ k_town_dwelling_minotaur,		"labyrinth" },
		{ k_town_dwelling_nightmare,	"nightmare" },
		{ k_town_dwelling_efreet,		"lava tube" },
		{ k_town_dwelling_hydra,		"hydra pond" },
		{ k_town_dwelling_black_dragon, "dragon cave" }
	};

	t_layout_layer_name const k_nature_layers[] =
	{
		{ k_town_mage_guild_1,  "mage guild 1" },
		{ k_town_mage_guild_2,	"mage guild 2" },
		{ k_town_mage_guild_3,	"mage guild 3" },
		{ k_town_mage_guild_4,	"mage guild 4" },
		{ k_town_mage_guild_5,	"mage guild 5" },
		{ k_town_library_1,				"chaos library" },
		{ k_town_library_2,				"life library" },
		{ k_town_portal,				"creature portal" },
		{ k_town_rainbow,				"rainbow" },
		{ k_town_grove,					"grove" },
		{ k_town_dwelling_wolf,			"wolf den" },
		{ k_town_dwelling_fairie,		"fae trees" },
		{ k_town_dwelling_tiger,		"tiger den" },
		{ k_town_dwelling_elf,			"homestead" },
		{ k_town_dwelling_griffin,		"griffin cliffs" },
		{ k_town_dwelling_unicorn,		"unicorn glade" },
		{ k_town_dwelling_pheonix,		"funeral pyre" },
		{ k_town_dwelling_fairie_dragon, "magic forest" }
	};

	t_layout_layer_name const k_might_layers[] =
	{
		{ k_town_breeding_pit,			"breeding pit" },
		{ k_town_magic_dampener,		"magic dampener" },
		{ k_town_arena,					"arena" },
		{ k_town_training_grounds,		"training grounds" },
		{ k_town_dwelling_berserker,	"berserker" },
		{ k_town_dwelling_centaur,		"centaur stables" },
		{ k_town_dwelling_nomad,		"nomad camp" },
		{ k_town_dwelling_harpy,		"harpy nest" },
		{ k_town_dwelling_ogre,			"ogre fort" },
		{ k_town_dwelling_cyclops,		"cyclops cave" },
		{ k_town_dwelling_thunderbird,	"cliff nest" },
		{ k_town_dwelling_behemoth,		"behemoth crag" }
	};
}; // unnamed namespace

std::vector<t_creature_type> const& get_portal_creature_types()
{
	// create creature rings
	static t_creature_type const k_creatures[] =
	{
		k_leprechaun,
		k_satyr,
		k_air_elemental,
		k_earth_elemental,
		k_fire_elemental,
		k_water_elemental,
		k_waspwort,
		k_mantis,
	};
	static bool							initialized = false;
	static std::vector<t_creature_type>	creatures;

	if (!initialized)
	{
		int	i;

		initialized = true;
		for (i = 0; i < ELEMENTS_OF( k_creatures ); ++i)
		{
			creatures.push_back( k_creatures[i] );
		}
	}
	return creatures;
}

// --------------------------------------------------------------------
// initialize layer names
// --------------------------------------------------------------------
static void init_layer_names( t_town_type town_type, t_layout_layer_name const* names,
							  int count )
{
	while (count--)
	{
		k_building_traits[town_type][names->id].keyword = names->name;
		names++;
	}
}

static void init_layer_names()
{
	int i, j;

	for (i = 0; i < k_town_type_count; i++)
		for (j = 0; j < ELEMENTS_OF( k_building_traits ); j++)
			k_building_traits[i][j].keyword = 0;

	for (i = 0; i < k_town_type_count; i++)
		init_layer_names( t_town_type(i), k_common_layers, ELEMENTS_OF( k_common_layers ));

	init_layer_names( k_town_life, k_life_layers, ELEMENTS_OF( k_life_layers ));
	init_layer_names( k_town_order, k_order_layers, ELEMENTS_OF( k_order_layers ));
	init_layer_names( k_town_death, k_death_layers, ELEMENTS_OF( k_death_layers ));
	init_layer_names( k_town_chaos, k_chaos_layers, ELEMENTS_OF( k_chaos_layers ));
	init_layer_names( k_town_nature, k_nature_layers, ELEMENTS_OF( k_nature_layers ));
	init_layer_names( k_town_might, k_might_layers, ELEMENTS_OF( k_might_layers ));
}

// ------------------------------------------------------------
// find building traits with a given keyword
// ------------------------------------------------------------
static t_building_traits* find_traits( t_town_type town, std::string const& keyword )
{
	int i;

	for (i = 0; i < k_town_building_count; i++)
		if (k_building_traits[town][i].keyword != 0
			&& stricmp( k_building_traits[town][i].keyword, keyword.c_str() ) == 0)
			return &k_building_traits[town][i];
	return 0;
}

// ------------------------------------------------------------
// set creature dwellings
// ------------------------------------------------------------
static void set_creature_dwellings()
{
	int i;
	t_town_building building;
	t_town_type     town_type;

	for (i = 0; i < k_creature_type_count; i++)
	{
		t_creature_traits const& creature_traits = get_traits( t_creature_type(i) );
		
		building = creature_traits.dwelling;
		town_type = creature_traits.alignment;
		if (town_type == k_town_type_count || building == k_town_no_building)
			continue;

		k_building_traits[town_type][building].creature = t_creature_type(i);
	}
}

// ------------------------------------------------------------
// read spreadsheet with attributes of town buildings
// ------------------------------------------------------------
static void read_traits()
{
	static bool initialized = false;

	if (initialized)
		return;
	initialized = true;

	// initialize keyword for buildings
	init_layer_names();

	t_table_ptr table = g_building_table.get();
	std::string keyword;

	t_table::iterator line;
	t_town_type       town = k_town_life;
	bool              town_begun = false;
	t_building_traits* traits;
	int                i;

	// for each line in the spreadsheet
	line = table->begin();
	line++;
	for (; line != table->end(); line++)
	{
		if (line->size() == 0)
			continue;

		keyword = line->front();
		if (keyword.empty())
		{
			if (town_begun)
			{
				town_begun = false;
				town = t_town_type( town + 1 );
				if (town == k_town_type_count)
					break;
			}
			continue;
		}

		town_begun = true;
		traits = find_traits( town, keyword );
		if (traits == 0)
			continue;

		traits->name = (*line)[1];
		
		for (i = 0; i < k_material_count; i++)
			traits->cost[i] = atoi( (*line)[i + 2].c_str() );

		traits->help_text = (*line)[9];
		traits->creature = k_creature_none;
	}
	set_creature_dwellings();
}

t_building_traits const& get_traits( t_town_type town, t_town_building building )
{
	read_traits();
	return k_building_traits[town][building];
}

// ------------------------------------------------------------------------------
// get keyword for a given fortification level
// ------------------------------------------------------------------------------
char const* get_town_image_keyword( t_town_image_level level )
{
	static char const* keywords[] = 
	{
		"village",
		"fort",
		"citadel",
		"castle"
	};
	return keywords[level];
}

// ------------------------------------------------------------------------------
// get model name for town given type, level, and facing
// ------------------------------------------------------------------------------

char const* get_town_model_name( t_town_type town, t_town_image_level image_level,
								 t_two_way_facing facing )
{
	static char const* model_names[k_town_type_count][k_town_image_count][k_two_way_facing_count] =
	{
		{
			{ "castle.haven.village",	"castle.haven.village R" },
			{ "castle.haven.fort",		"castle.haven.fort R" },
			{ "castle.haven.citadel",	"castle.haven.citadel R" },
			{ "castle.haven.castle",	"castle.haven.castle R" },
		},
		{
			{ "castle.academy.village",	"castle.academy.village R" },
			{ "castle.academy.fort",	"castle.academy.fort R" },
			{ "castle.academy.citadel",	"castle.academy.citadel R" },
			{ "castle.academy.castle",	"castle.academy.castle R" },
		},
		{
			{ "castle.necropolis.village",	"castle.necropolis.village R" },
			{ "castle.necropolis.fort",		"castle.necropolis.fort R" },
			{ "castle.necropolis.citadel",	"castle.necropolis.citadel R" },
			{ "castle.necropolis.castle",	"castle.necropolis.castle R" },
		},
		{
			{ "castle.asylum.village",	"castle.asylum.village R" },
			{ "castle.asylum.fort",		"castle.asylum.fort R" },
			{ "castle.asylum.citadel",	"castle.asylum.citadel R" },
			{ "castle.asylum.castle",	"castle.asylum.castle R" },
		},	
		{
			{ "castle.preserve.village",	"castle.preserve.village R" },
			{ "castle.preserve.fort",		"castle.preserve.fort R" },
			{ "castle.preserve.citadel",	"castle.preserve.citadel R" },
			{ "castle.preserve.castle",		"castle.preserve.castle R" },
		},
		{
			{ "castle.stronghold.village",	"castle.stronghold.village R" },
			{ "castle.stronghold.fort",		"castle.stronghold.fort R" },
			{ "castle.stronghold.citadel",	"castle.stronghold.citadel R" },
			{ "castle.stronghold.castle",	"castle.stronghold.castle R" },
		}
	};

	return model_names[town][image_level][facing];
}
